#include "../utils/Logger.h"
#include "Flight.h"

#include <errno.h>
#include <iostream>
#include "../utils/SimulatorUtils.h"
#include "../comunication/DTO/DTOFlightToLand.h"
#include "../comunication/DTO/DTOFlightToTakeOff.h"

Flight::Flight(unsigned int flightId,Status state) :inbox(SimulatorUtils::getFlighInboxName(flightId)),tcI(SimulatorUtils::getTowerInboxName()),state(state){
	this->flightId = flightId;
	this->isRunning = true;
	this->log = Logger::instancia();

	inbox.crear();

	//tcI.openForWrite();
}
Flight::~Flight(){
	//Cierro el inbox para el vuelo
	log << "Flight::Flight - Cierro Inbox propio.flightId:" << flightId << eol;
	inbox.cerrar();
	inbox.eliminar();

	tcI.cerrar();
}

void Flight::takeOff(){
	//Cambio a transicion de taking off
	this->state.startTransition(TAKING_OFF);
}

void Flight::land(){
	//Cambio a transicion de taking off
	this->state.startTransition(LANDING);
}

//Una vez que toca tierra puede estacionar
void Flight::changeStatus(Status s){
	//Cambio a transicion de taking off
	this->state.startTransition(s);
}
const FlightState Flight::getState(){
	return (this->state);
}

unsigned int Flight::getFlightId(){
	return (this->flightId);
}

DTOFlightRelated Flight::getDTO(){
	DTOFlight flightDTO = DTOFlight(this->flightId,this->state.getStatus());

	if (this->state.getStatus() == IN_THE_AIR){
		return (DTOFlightToLand(flightDTO));
	}

	return (DTOFlightToTakeOff(flightDTO));
}


int Flight::run() {
	log << "Flight::run - Running the Flight:" << flightId << " -pid:" << getpid() <<eol;

	//Me comunico con la torre de control
	tcI.newFlightArrival(this->getDTO());

	log << "Flight::run - Informe mi request a los controllers - FlightId:" <<this->flightId <<eol;

	while (this->isRunning) {
		log << "Flight::run - Espero mensaje a procesar flightId:" << flightId << eol;
		DTO* dto = inbox.leerDTO();
		log << "Flight::run - Obtuve mensaje a procesar flightId:" << flightId <<eol;

		switch (dto->getType()) {
			case FLIGHT:{
				log << "Flight::run - Lei FLIGHT" << eol;
				DTOFlight* dtoFlight = (DTOFlight*)dto;
				this->state.startTransition((Status)dtoFlight->getState());

				log << "Flight::run - Estado final : " << this->state.getStatus() << " - Runway id: " << dtoFlight->getRunwayId() << " -FlightId:" << flightId << eol;

				//Abro conexion a torre de control y envio mensaje y vuelvo a salir
				tcI.releaseRunway(dtoFlight->getRunwayId());

				//FIN de la operacion, indique q liberen la pista!
				log << "Flight::run - Marco fin de operaciones para el vuelo flightId:" << flightId << eol;
				this->isRunning= false;

			}break;
			default:
				log << "ERROR : Flight::run - Recibi un mensaje que no se procesar!!! - Tipo: " << dto->getType() << eol;
				break;
		}

		delete dto;
	}



	log << "Flight::run - Termino el Flight.flightId:" << flightId << eol;

	return 0;
}

